package main;

import bots.MinMaxClassifierBot;
import bots.lookahead.LightLookAheadBot;
import bots.lookahead.SimpleLookAheadBot;
import bots.lookahead.SuperLookAheadBot;
import classification.ClassifierMLRegressionAdapter;
import model.Classifier;
import model.GameState;
import model.GameType;
import model.Player;
import org.apache.log4j.Logger;
import util.Util;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ForkJoinPool;

/**
 * @author Alex Vikharev vikharev@yandex-team.ru
 *         created 17.02.12
 */
public class BotVSBotGame {
    private final static Logger log = Logger.getLogger(BotVSBotGame.class);

    public static void main(String[] args) throws IOException {
        ForkJoinPool pool = new ForkJoinPool();
//        Player bot0 = new SimpleLookAheadBot(GameType.IMPROVED, "LightLookAhead(0)", 0, pool);
//        Player bot1 = new SimpleLookAheadBot(GameType.IMPROVED, "LightLookAhead(1)", 1, pool);
        LightLookAheadBot bot2 = new LightLookAheadBot(GameType.IMPROVED, "LightLookAhead(2)", 2, pool, false);
//        LightLookAheadBot bot3 = new LightLookAheadBot(GameType.IMPROVED, "LightLookAhead(3)", 3, pool);
//        SuperLookAheadBot bot4 = new SuperLookAheadBot("SuperLookAhead", GameType.IMPROVED, pool);
//        SuperLookAheadBot bot5 = new SuperLookAheadBot("SuperLookAhead-2", GameType.IMPROVED, pool);

        Classifier neuralClassifier = new ClassifierMLRegressionAdapter(Util.loadClassifier("network.ser"));
        MinMaxClassifierBot neuralBot = new MinMaxClassifierBot("Neural", neuralClassifier, GameType.IMPROVED);

//        play(bot0, bot1, "LightLookAhead(0x1)games100000", 100000);
//        play(bot1, bot0, "LightLookAhead(1x0)games100000", 100000);
//        play(bot1, bot11, "LightLookAhead(1x1)games100000", 100000);
//        play(bot1, bot2, "LightLookAhead(1x2)games100000", 100000);
//        play(bot2, bot1, "LightLookAhead(2x1)games100000", 100000);
//        play(bot2, bot21, "LightLookAhead(2x2)games100000", 100000);
//        play(bot2, bot3, "LightLookAhead(2x3)games100000", 100000);
//        play(bot3, bot2, "LightLookAhead(3x2)games100000", 100000);
//        play(bot3, bot3, "LightLookAhead(3x3)games100000", 100000);
//        play(bot4, bot0, "games1000_S_vs_SLA0", 1000);
//        play(bot0, bot4, "games1000_SLA0_vs_S", 1000);
//
//        play(bot4, bot1, "games1000_S_vs_SLA1", 1000);
//        play(bot1, bot4, "games1000_SLA1_vs_S", 1000);
//
//        play(bot4, bot2, "games1000_S_vs_LLA2", 1000);
//        play(bot2, bot4, "games1000_LLA2_vs_S", 1000);
//
//        play(bot4, bot3, "games1000_S_vs_LLA3", 1000);
//        play(bot3, bot4, "games1000_LLA3_vs_S", 1000);
//
//        play(bot4, bot5, "games1000_S_vs_S", 2000);


        play(bot2, neuralBot, 100);
        pool.shutdown();
    }

    private static void play(final Player bot1, final Player bot2, final String filename, final int count) throws IOException {
        BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(filename));
        int firstWin = 0;
        int secondWin = 0;
        for (int i = 0; i < count; i++) {
            log.info("Game " + filename + " games played: " + i);
            log.info(bot1 + " win: " + firstWin + " " + bot2 + " win: " + secondWin);
            Game game = new Game(bot1, bot2, GameType.IMPROVED);
            game.go();
            if (game.getState() == GameState.FIRST_PLAYER_WIN) {
                firstWin++;
            } else if (game.getState() == GameState.SECOND_PLAYER_WIN) {
                secondWin++;
            }
            output.write(game.getGameRecord().toBytes());
        }
        output.close();
    }

    private static void play(final Player bot1, final Player bot2, final int count) throws IOException {
        int firstWin = 0;
        int secondWin = 0;
        for (int i = 0; i < count; i++) {
            log.info(String.format("Games played: %d %s wins: %d %s wins: %d", i, bot1, firstWin, bot2, secondWin));
            Game game = new Game(bot1, bot2, GameType.IMPROVED);
            game.go();
            if (game.getState() == GameState.FIRST_PLAYER_WIN) {
                firstWin++;
            } else if (game.getState() == GameState.SECOND_PLAYER_WIN) {
                secondWin++;
            }
        }
        log.info(String.format("%s wins: %d %s wins: %d", bot1, firstWin, bot2, secondWin));
    }

}
